package io.kiki.stack.netty.config.switches;

import lombok.Getter;
import lombok.Setter;

import java.util.BitSet;

@Setter
@Getter
public class ProtocolSwitch implements Switch {

    // switch index
    public static final int CRC_SWITCH_INDEX = 0x000;
    // default value
    public static final boolean CRC_SWITCH_DEFAULT_VALUE = true;
    private BitSet bitSet = new BitSet();

    public static ProtocolSwitch create(int value) {
        ProtocolSwitch protocolSwitch = new ProtocolSwitch();
        protocolSwitch.setBitSet(toBitSet(value));
        return protocolSwitch;
    }

    public static ProtocolSwitch create(int[] index) {
        ProtocolSwitch protocolSwitch = new ProtocolSwitch();
        for (int i = 0; i < index.length; ++i) {
            protocolSwitch.turnOn(index[i]);
        }
        return protocolSwitch;
    }

    public static boolean isOn(int value, int switchIndex) {
        return toBitSet(value).get(switchIndex);
    }

    /**
     * from byte to bit set
     */
    public static BitSet toBitSet(int value) {
        if (value < 0 || value > Byte.MAX_VALUE) {
            throw new IllegalArgumentException("The value " + value + " is out of byte range, should be limited between [0] to [" + Byte.MAX_VALUE + "]");
        }
        BitSet bitSet1 = new BitSet();
        int index = 0;
        while (value != 0) {
            if (value % 2 != 0) {
                bitSet1.set(index);
            }
            ++index;
            value = (byte) (value >> 1);
        }
        return bitSet1;
    }

    public static byte toByte(BitSet bitSet) {
        int value = 0;
        for (int i = 0; i < bitSet.length(); ++i) {
            if (bitSet.get(i)) {
                value += 1 << i;
            }
        }
        if (bitSet.length() > 7) {
            throw new IllegalArgumentException("The byte value " + value + " generated according to bit set " + bitSet + " is out of range, should be limited between [0] to [" + Byte.MAX_VALUE + "]");
        }
        return (byte) value;
    }

    @Override
    public void turnOn(int index) {
        this.bitSet.set(index);
    }

    @Override
    public void turnOff(int index) {
        this.bitSet.clear(index);
    }

    @Override
    public boolean isOn(int index) {
        return this.bitSet.get(index);
    }

    public byte toByte() {
        return toByte(this.bitSet);
    }


}